package com.springboot.blog.controller.admin;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.springboot.blog.dto.LayPage;
import com.springboot.blog.dto.LayResponse;
import com.springboot.blog.entity.Menu;
import com.springboot.blog.entity.Role;
import com.springboot.blog.interfaces.ToolInterface;
import com.springboot.blog.service.IMenuService;
import com.springboot.blog.service.IRoleService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@Controller
class AdminRoleController {
    @Autowired
    IRoleService roleService;
    @Autowired
    IMenuService menuService;
    String PATH = "admin/role/";

    @RequiresPermissions("role:list")
    @GetMapping(value = {"/admin/role/index", "/admin/role"})
    public String index() {
        return PATH + "index";
    }

    @RequiresPermissions("role:list")
    @GetMapping(value = {"/admin/role/tree"})
    @ResponseBody
    public LayResponse tree(Integer page, Integer limit) {
        page = page == null ? 1 : page;
        limit = limit == null ? 10 : limit;
        LayPage<Role> pageRole = new LayPage<>(page, limit);
        roleService.page(pageRole);
        return pageRole.getLayResponse();
    }

    @RequiresPermissions("role:delete")
    @PostMapping(value = {"/admin/role/delete"})
    @ResponseBody
    public LayResponse delete(String id) {
        boolean result = roleService.removeById(id);
        LayResponse layResponse = new LayResponse();
        if (result) {
            return layResponse.success();
        }
        return layResponse.error();
    }

    @RequiresPermissions("role:delete")
    @PostMapping(value = {"/admin/role/deleteAll"})
    @ResponseBody
    public LayResponse deleteAll(@RequestParam("ids[]") List<Integer> ids) {
        boolean result = roleService.removeByIds(ids);
        LayResponse layResponse = new LayResponse();
        if (result) {
            return layResponse.success();
        }
        return layResponse.error();
    }

    @RequiresPermissions("role:add")
    @GetMapping(value = {"/admin/role/add"})
    public String add(Model model) {
        List<Map<String, Object>> maps = menuService.listMaps(new LambdaQueryWrapper<Menu>().orderByAsc(Menu::getSorts));
        List<Map<String, Object>> tree = new ArrayList<>();
        buildTreeData(maps, tree, 0);
        model.addAttribute("tree", new Gson().toJson(tree));
        return PATH + "add";
    }

    private void buildTreeData(List<Map<String, Object>> list, List<Map<String, Object>> tree, long parentId) {
        for (Map<String, Object> row : list) {
            if ((long) row.get("pid") == parentId) {
                List<Map<String, Object>> children = new ArrayList<>();
                buildTreeData(list, children, (long) row.get("id"));
                if (!children.isEmpty()) {
                    row.put("spread", true);
                }
                row.put("children", children);
                tree.add(row);
            }
        }
    }

    @RequiresPermissions("role:add")
    @PostMapping(value = {"/admin/role/add"})
    @ResponseBody
    public LayResponse add(@Validated(ToolInterface.insert.class) Role role) {
        roleService.save(role);
        return new LayResponse().success();
    }

    @RequiresPermissions("role:edit")
    @GetMapping(value = {"/admin/role/edit"})
    public String edit(@RequestParam String id, Model model) {
        Role data = roleService.getById(id);
        List<String> rules = Arrays.asList(data.getRules().split(","));
        List<Map<String, Object>> maps = menuService.listMaps(new LambdaQueryWrapper<Menu>().orderByAsc(Menu::getSorts));
        List<Map<String, Object>> tree = new ArrayList<>();
        buildTreeData2(maps, rules, tree, 0);
        model.addAttribute("tree", new Gson().toJson(tree));
        model.addAttribute("data", data);
        return PATH + "edit";
    }

    private void buildTreeData2(List<Map<String, Object>> list, List<String> rules, List<Map<String, Object>> tree, long parentId) {
        for (Map<String, Object> row : list) {
            if ((long) row.get("pid") == parentId) {
                List<Map<String, Object>> children = new ArrayList<>();
                buildTreeData2(list,rules, children, (long) row.get("id"));
                row.put("children", children);
                if (children.isEmpty()) {
                    if (rules.contains(row.get("id").toString())) {
                        row.put("checked", true);
                    }
                } else {
                    row.put("spread", true);
                }
                tree.add(row);
            }
        }
    }

    @RequiresPermissions("role:edit")
    @PostMapping(value = {"/admin/role/edit"})
    @ResponseBody
    public LayResponse edit(@Validated(ToolInterface.update.class) Role role) {
        roleService.updateById(role);
        return new LayResponse().success();
    }

    @RequiresPermissions("role:edit")
    @PostMapping(value = {"/admin/role/ajax"})
    @ResponseBody
    public LayResponse ajax(Role role) {
        boolean b = roleService.updateById(role);
        LayResponse layResponse = new LayResponse();
        if (b) {
            return layResponse.success();
        }
        return layResponse.error();
    }
}
